package pl.edu.agh.administracja.networkconfig.model.util;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import pl.edu.agh.administracja.networkconfig.model.PasswordHolder;

/**
 *
 * @author piotrek
 */
public class ShellExecutor {

    private static final BlockingQueue<Runnable> asynchronousTasksQueue = new LinkedBlockingQueue<Runnable>();
    private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 10, 5000, TimeUnit.MILLISECONDS, asynchronousTasksQueue);
    private static int latestCommandRetValue = 0;

    public static int getLatestCommandRetValue() {
        return latestCommandRetValue;
    }

    private ShellExecutor() {
    }

    /**
     * Wykonuje w sposob synchroniczny komende w wierszy polecen i zwraca wynik.
     *
     * @param command komenda do wykonania
     * @return rezultat z wiersza polecen
     */
    public static String executeSynchronously(final String command) {
        try {

            Runtime rt = Runtime.getRuntime();
            Process pr = rt.exec(new String[]{"/bin/sh", "-c", command}, new String[]{"LANG=C"});

            latestCommandRetValue = pr.waitFor();

            BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));

            StringBuilder builder = new StringBuilder();
            String line;
            while ((line = input.readLine()) != null) {
                builder.append(line);
                builder.append("\n");
            }

            return builder.toString();

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    public static String executeSynchronouslyAsRoot(final String command) {
        String password = PasswordHolder.getPassword();
        return executeSynchronously("echo '" + password + "' | sudo -S sh -c '" + command + "'");
    }

    /**
     * Wykonuje komende w wierszu polecen asynchronicznie, a potem wola callback
     * przekazujac w parametrze rezultat z wiersza polecen.
     *
     * @param command komenda do wykonania
     * @param callback obiekt callback
     */
    public static void executeAsynchronously(final String command, final ShellTaskCallback callback) {

        executor.execute(new Runnable() {

            @Override
            public void run() {
                callback.execute(executeSynchronously(command));
            }
        });
    }
}
